# -*- coding: utf-8 -*-
import time
import torch_npu
import torch
import random
import json
import numpy as np
import pandas as pd
from datetime import datetime, timedelta

from sympy.physics.units import action

day_list = [24,
             93, 94,95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
             123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
             154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
             184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
             215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
             246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
             274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
             305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
             335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360,
             1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
             31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
             62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
             125, 36, 62, 322, 37, 281, 315, 363, 328, 319, 60, 138, 326, 223, 27, 166, 199, 338, 311, 116, 158, 176, 70, 44, 209, 239, 282, 97, 140, 130, 191, 361,
             177, 56, 1, 339, 168, 244, 145, 359, 257, 25, 151, 147, 103, 33, 182, 121, 354, 78, 213, 352, 303, 232, 200, 229, 48, 38, 47, 297, 314, 320, 139, 55, 202,
             211, 129, 2, 22, 134, 301, 87, 172, 300, 340, 334, 51, 347, 330, 249, 302, 226, 235, 74, 284, 152, 34, 28, 111, 255, 337, 164, 132, 342, 73, 261, 161, 12,
             260, 85, 237, 114, 210, 225, 293, 256, 32, 269, 53, 195, 42, 187, 206, 266, 207, 295, 72, 252, 291, 307, 92, 71, 321, 231, 113, 143, 89, 165, 171, 203,
             101, 91, 64, 247, 345, 141, 41, 262, 67, 26, 52, 312, 159, 351, 19, 306, 65, 224, 279, 183, 162, 98, 50, 35, 160, 228, 155, 154, 29, 254, 124, 156, 9, 11,
             272, 329, 123, 108, 43, 350, 304, 204, 148, 3, 197, 343, 13, 118, 119, 344, 273, 150, 142, 99, 90, 275, 305, 357, 286, 296, 149, 137, 277, 309, 69, 122,
             126, 250, 358, 117, 230, 146, 348, 214, 335, 188, 39, 264, 271, 17, 66, 253, 299, 288, 251, 68, 102, 45, 285, 259, 267, 324, 317, 222, 170, 104, 245, 21,
             128, 40, 190, 80, 258, 201, 310, 93, 18, 6, 356, 46, 292, 8, 181, 355, 193, 220, 265, 23, 95, 61, 24, 110, 5, 178, 136, 364, 219, 81, 218, 227, 186, 144,
             341, 131, 323, 106, 76, 14, 289, 217, 20, 360, 82, 205, 274, 10, 240, 185, 238, 346, 167, 336, 54, 365, 318, 248, 75, 173, 112, 212, 120, 115, 243, 290, 196]
day_list1 = [93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
             123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
             154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
             184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
             215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
             246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
             274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
             305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
             335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360,
             1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
             31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
             62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
             125, 36, 62, 322, 37, 281, 315, 363, 328, 319, 60, 138, 326, 223, 27, 166, 199, 338, 311, 116, 158, 176, 70, 44, 209, 239, 282, 97, 140, 130, 191, 361,
             177, 56, 1, 339, 168, 244, 145, 359, 257, 25, 151, 147, 103, 33, 182, 121, 354, 78, 213, 352, 303, 232, 200, 229, 48, 38, 47, 297, 314, 320, 139, 55, 202,
             211, 129, 2, 22, 134, 301, 87, 172, 300, 340, 334, 51, 347, 330, 249, 302, 226, 235, 74, 284, 152, 34, 28, 111, 255, 337, 164, 132, 342, 73, 261, 161, 12,
             260, 85, 237, 114, 210, 225, 293, 256, 32, 269, 53, 195, 42, 187, 206, 266, 207, 295, 72, 252, 291, 307, 92, 71, 321, 231, 113, 143, 89, 165, 171, 203,
             101, 91, 64, 247, 345, 141, 41, 262, 67, 26, 52, 312, 159, 351, 19, 306, 65, 224, 279, 183, 162, 98, 50, 35, 160, 228, 155, 154, 29, 254, 124, 156, 9, 11,
             272, 329, 123, 108, 43, 350, 304, 204, 148, 3, 197, 343, 13, 118, 119, 344, 273, 150, 142, 99, 90, 275, 305, 357, 286, 296, 149, 137, 277, 309, 69, 122,
             126, 250, 358, 117, 230, 146, 348, 214, 335, 188, 39, 264, 271, 17, 66, 253, 299, 288, 251, 68, 102, 45, 285, 259, 267, 324, 317, 222, 170, 104, 245, 21,
             128, 40, 190, 80, 258, 201, 310, 93, 18, 6, 356, 46, 292, 8, 181, 355, 193, 220, 265, 23, 95, 61, 24, 110, 5, 178, 136, 364, 219, 81, 218, 227, 186, 144,
             341, 131, 323, 106, 76, 14, 289, 217, 20, 360, 82, 205, 274, 10, 240, 185, 238, 346, 167, 336, 54, 365, 318, 248, 75, 173, 112, 212, 120, 115, 243, 290, 196,
             275, 22, 1, 202, 63, 161, 265, 24, 113, 148, 295, 130, 345, 194, 85, 96, 142, 203, 23, 53, 207, 13, 106,
             72, 324, 19, 237, 131, 154, 52, 42, 221, 8, 66, 78, 175,
             217, 184, 77, 281, 208, 352, 11, 73, 193, 224, 201, 108, 110, 173, 71, 305, 7, 76, 293, 56, 44, 348, 328,
             64, 48, 116, 204, 225, 174, 177, 33, 192, 285, 69, 260,
             144, 104, 178, 326, 283, 143, 102, 140, 289, 172, 296, 38, 133, 3, 298, 126, 235, 125, 264, 256, 101, 234,
             254, 314, 10, 206, 195, 167, 190, 358, 287, 344, 313,
             186, 100, 95, 98, 74, 187, 166, 232, 205, 165, 297, 200, 14, 250, 343, 160, 308, 336, 236, 284, 21, 15, 2,
             277, 188, 138, 253, 37, 50, 112, 355, 176, 288, 4, 134,
             155, 249, 31, 97, 274, 322, 230, 359, 17, 107, 81, 339, 158, 127, 80, 16, 12, 115, 266, 356, 312, 357, 163,
             255, 170, 93, 340, 94, 329, 349, 168, 209, 246, 169, 310,
             278, 20, 233, 231, 35, 354, 259, 34, 319, 248, 157, 199, 294, 132, 223, 32, 111, 229, 51, 315, 252, 350,
             137, 87, 109, 299
             ]

test_day_list = [26, 27, 28, 29, 30, 57, 58, 59, 60, 61, 88, 89, 90, 91, 92, 118, 119, 120, 121, 122, 149, 150, 151, 152, 153, 179, 180, 181, 182, 183,
                 210, 211, 212, 213, 214, 240, 241, 242, 243, 244, 245, 268, 269, 270, 271, 272, 273, 300, 301, 302, 303, 304, 330, 331, 332, 333, 334,
                 361, 362, 363, 364, 365]
# print(len(test_day_list))

day_list_add = [275, 22, 1, 202, 63, 161, 265, 24, 113, 148, 295, 130, 345, 194, 85, 96, 142, 203, 23, 53, 207, 13, 106, 72, 324, 19, 237, 131, 154, 52, 42, 221, 8, 66, 78, 175,
                217, 184, 77, 281, 208, 352, 11, 73, 193, 224, 201, 108, 110, 173, 71, 305, 7, 76, 293, 56, 44, 348, 328, 64, 48, 116, 204, 225, 174, 177, 33, 192, 285, 69, 260,
                144, 104, 178, 326, 283, 143, 102, 140, 289, 172, 296, 38, 133, 3, 298, 126, 235, 125, 264, 256, 101, 234, 254, 314, 10, 206, 195, 167, 190, 358, 287, 344, 313,
                186, 100, 95, 98, 74, 187, 166, 232, 205, 165, 297, 200, 14, 250, 343, 160, 308, 336, 236, 284, 21, 15, 2, 277, 188, 138, 253, 37, 50, 112, 355, 176, 288, 4, 134,
                155, 249, 31, 97, 274, 322, 230, 359, 17, 107, 81, 339, 158, 127, 80, 16, 12, 115, 266, 356, 312, 357, 163, 255, 170, 93, 340, 94, 329, 349, 168, 209, 246, 169, 310,
                278, 20, 233, 231, 35, 354, 259, 34, 319, 248, 157, 199, 294, 132, 223, 32, 111, 229, 51, 315, 252, 350, 137, 87, 109, 299, 125, 36, 62, 322, 37, 281, 315, 363, 328, 319, 
                60, 138, 326, 223, 27, 166, 199, 338, 311, 116, 158, 176, 70, 44, 209, 239, 282, 97, 140, 130, 191, 361, 177, 56, 1, 339, 168, 244, 145, 359, 257, 25, 151, 147, 103, 33, 
                182, 121, 354, 78, 213, 352, 303, 232, 200, 229, 48, 38, 47, 297, 314, 320, 139, 55, 202,  211, 129, 2, 22, 134, 301, 87, 172, 300, 340, 334, 51, 347, 330, 249, 302, 226, 235, 
                74, 284, 152, 34, 28, 111, 255, 337, 164, 132, 342, 73, 261, 161, 12, 260, 85, 237, 114, 210, 225, 293, 256, 32, 269, 53, 195, 42, 187, 206, 266, 207, 295, 72, 252, 291, 307, 
                92, 71, 321, 231, 113, 143, 89, 165, 171, 203,101, 91, 64, 247, 345, 141, 41, 262, 67, 26, 52, 312, 159, 351, 19, 306, 65, 224, 279, 183, 162, 98, 50, 35, 160, 228, 155, 
                154, 29, 254, 124, 156, 9, 11,272, 329, 123, 108, 43, 350, 304, 204, 148, 3, 197, 343, 13, 118, 119, 344, 273, 150, 142, 99, 90, 275, 305, 357, 286, 296, 149, 137, 277, 309, 69, 122,
             126, 250, 358, 117, 230, 146, 348, 214, 335, 188, 39, 264, 271, 17, 66, 253, 299, 288, 251, 68, 102, 45, 285, 259, 267, 324, 317, 222, 170, 104, 245, 21,
             128, 40, 190, 80, 258, 201, 310, 93, 18, 6, 356, 46, 292, 8, 181, 355, 193, 220, 265, 23, 95, 61, 24, 110, 5, 178, 136, 364, 219, 81, 218, 227, 186, 144,
             341, 131, 323, 106, 76, 14, 289, 217, 20, 360, 82, 205, 274, 10, 240, 185, 238, 346, 167, 336, 54, 365, 318, 248, 75, 173, 112, 212, 120, 115, 243, 290, 196,217, 
            184, 77, 281, 208, 352, 11, 73, 193, 224, 201, 108, 110, 173, 71, 305, 7, 76, 293, 56, 44, 348, 328,
             64, 48, 116, 204, 225, 174, 177, 33, 192, 285, 69, 260,
             144, 104, 178, 326, 283, 143, 102, 140, 289, 172, 296, 38, 133, 3, 298, 126, 235, 125, 264, 256, 101, 234,
             254, 314, 10, 206, 195, 167, 190, 358, 287, 344, 313,
             186, 100, 95, 98, 74, 187, 166, 232, 205, 165, 297, 200, 14, 250, 343, 160, 308, 336, 236, 284, 21, 15, 2,
             277, 188, 138, 253, 37, 50, 112, 355, 176, 288, 4, 134,
             155, 249, 31, 97, 274, 322, 230, 359, 17, 107, 81, 339, 158, 127, 80, 16, 12, 115, 266, 356, 312, 357, 163,
             255, 170, 93, 340, 94, 329, 349, 168, 209, 246, 169, 310,]

extrame_list = [3, 24, 26, 30, 35, 41, 49, 57, 59, 62, 64, 65, 68, 69, 74, 76, 80, 85, 88, 89, 112, 143, 171, 213, 214, 216, 221, 222, 223, 230, 233, 243, 258, 259,
                273, 278, 288, 293, 318, 321, 331, 342, 344, 357, 362 ]

p_list =[[0.4, 0.6], [0.325, 0.675], [0.925, 0.075], [0.875, 0.125], [0.35, 0.65], [0.25, 0.75], [0.9, 0.1], [0.05, 0.95], [0.8, 0.2],
         [0.475, 0.525], [0.825, 0.175], [0.9, 0.1], [0.25, 0.75], [0.625, 0.375], [0.35, 0.65], [0.1, 0.9], [0.475, 0.525], [0.5, 0.5],
         [0.875, 0.125], [0.375, 0.625], [0.45, 0.55], [0.325, 0.675], [0.775, 0.225], [0.975, 0.025], [0.05, 0.95], [0.35, 0.65], [0.325, 0.675],
         [0.6, 0.4], [0.05, 0.95], [0.75, 0.25], [0.7, 0.3], [0.725, 0.275], [0.825, 0.175], [0.425, 0.575], [0.175, 0.825], [0.3, 0.7],
         [0.625, 0.375], [0.375, 0.625], [0.25, 0.75], [0.825, 0.175], [0.225, 0.775], [0.15, 0.85], [0.425, 0.575], [0.05, 0.95], [0.775, 0.225],
         [0.925, 0.075], [0.475, 0.525], [0.3, 0.7], [0.175, 0.825], [0.925, 0.075], [0.9, 0.1], [0.15, 0.85], [0.425, 0.575], [0.6, 0.4],
         [0.325, 0.675], [0.175, 0.825], [0.325, 0.675], [0.75, 0.25], [0.375, 0.625], [0.125, 0.875], [0.625, 0.375], [0.175, 0.825]]



class ElectricBusChargingEnv:
    def __init__(self, config_path='config.json', base_date=datetime(2020, 6, 1)):
        self.base_date = base_date
        self.config = self.load_config(config_path)

        # 加载公交车和线路配置
        self.num_lines = self.config['num_lines']
        self.line_periods = self.config['line_periods']
        self.line_timing_details = self.config['line_timing_details']
        self.num_buses_per_line = self.config['num_buses_per_line']
        self.num_buses = sum(self.num_buses_per_line.values())
        self.mileage = self.config['mileage']
        self.route_average_consumptiomn = self.config['Average_energy']

        # 加载公交车特定配置
        self.bus_mass = self.config['bus_config']['F_k']
        self.optimal_temperature = self.config['bus_config']['kappa_star']
        self.bus_capacity = self.config['bus_config']['capacity']
        self.bus_battery_SOH = self.config['bus_config']['SOH']
        self.bus_max_soc = self.config['bus_config']['SOC_MAX']
        self.bus_min_soc = self.config['bus_config']['SOC_MIN']

        # 天气数据文件路径和加载
        self.weather_data_path = self.config['weather_data_path']

        # 光伏和储能系统配置
        self.pv_area = self.config['pv_system']['area']
        self.pv_efficiency = self.config['pv_system']['efficiency']
        self.pv_capacity = self.config['pv_system']['rated_power']
        self.temperature_coefficient = self.config['pv_system']['temperature_coefficient']
        self.pv_reference_temperature = self.config['pv_system']['reference_temperature']
        self.pv_normal_operating_temperature = self.config['pv_system']['normal_operating_temperature']
        self.pv_price = self.config['pv_system']['price']
        self.storage_capacity = self.config['storage_system']['capacity']
        self.storage_battery_SOH = self.config['storage_system']['SOH']
        self.storage_battery_max_soc = self.config['storage_system']['SOC_MAX']
        self.storage_battery_min_soc = self.config['storage_system']['SOC_MIN']
        self.storage_price = 0.3688

        # 充电桩配置
        self.charging_efficiency = self.config['charging_station']['efficiency']
        self.charging_station_number = self.config['charging_station']['number']
        self.MIN_CHARGING_TIME = self.config['charging_station']['MIN_CHARGING_TIME']
        self.P_CP = self.config['charging_station']['charging_power']

        # 充电电价
        self.grid = self.config["sg_price"]
        self.ess_count = 0
        self.ess_is_chaging = 0
        self.cqqqq = 0

        # 碳排放系数
        self.pv_carbon_emission_factor = self.config["carbon_emission_factor"]["pv"]
        self.sg_carbon_emission_factor = self.config["carbon_emission_factor"]["sg"]

        # 极端天气日期索引
        self.extrame_list = []
        # ！！！！！！！！！！！！！！！！！！！！！初始化其他可能的类属性  这部分需要在reset的时候再标准化
        self.load_weather_data()

    def load_config(self, path):
            """
            Load configuration from a JSON file.
            """
            try:
                with open(path, 'r') as file:
                    return json.load(file)
            except FileNotFoundError:
                print(f"Error: Configuration file not found at {path}")
                return {}
            except json.JSONDecodeError:
                print(f"Error: Configuration file is not a valid JSON at {path}")
                return {}


    def load_weather_data(self):
            self.weather_df = pd.read_csv(self.weather_data_path)
            self.weather_df['datetime'] = pd.to_datetime(self.weather_df['date'] + ' ' + self.weather_df['time'])


    def reset(self, day_number):
        self.time_step = 0
        self.storage_charging_period = []
        self.storage_charging_time = 0
        # 这个是干嘛的？
        # self.storage_energy_used = 0
        self.storage_soc = 0.8  # 假设储能系统的起始SOC为80%
        # self.actions_history = []  # 历史动作记录
        # self.cost_history = []  # 储存每个时段的成本累积
        self.storage_price = 0.3688
        self.bus_charging_time = [0] * self.num_buses
        self.bus_charging_periods = [[] for _ in range(self.num_buses)]
        self.finished_trips = {i: [] for i in range(1, self.num_buses + 1)}
        self.bus_soc = [0.8] * self.num_buses  # 假设每辆公交车的起始SOC为80%
        self.bus_soc_ini = [0.8] * self.num_buses  # 假设每辆公交车的起始SOC为80%
        self.charging_gain = [0.0] * self.num_buses  # 耗能只能一起算所以充电量也要一起算
        action_ini, storge_action_ini = self.reset_action()
        ini_prev_actions = (action_ini, storge_action_ini)
        # self.day_index = test_day_list[day_number]  # 用于测试
        self.day_index = day_list1[day_number]  #  用于训练
        '''''
        '''
        # self.day_index = day_list1[day_number]
        # self.day_index = 244  #  用于绘图
        # self.day_index = day_list_add[day_number]
        # print('self.day_index',self.day_index)

        self.current_date = self.base_date + timedelta(days=self.day_index - 1)
        current_datetime = self.step_to_datetime(self.time_step)
        # 这个是用来生成发车时间的
        self.timetables = self.generate_timetables()
        # print(self.timetables)

        # 确定每辆车所跑的班次编号
        self.vehicle_schedules = self.assign_trips_to_buses()

        # 更清晰的看到各线路各车辆的班次信息
        self.schedules = self.unify_bus_numbers()

        # 获取当日的天气信息便于后续的处理
        self.daily_data = self.weather_df[self.weather_df['datetime'].dt.date == self.current_date.date()]
        # print(' self.daily_data',  self.daily_data)
        # 生成每个班次的信息，包含开始时间结束时间、平均温度、光照强度等
        self.trip_weather_info = self.get_trip_weather_info()
        # print('sdojfcposjupiodufpodsfuop',self.trip_weather_info)

        self.route_average_consumptiomn = self.calculate_average_energy_per_route(self.trip_weather_info)
        # # 获得初始状态
        state = self.get_current_state(action_ini, storge_action_ini, storge_charge_energy = 0)

        self.sg_price = self.get_grid_price()

        if self.day_index in extrame_list:
            is_extrame = True
        else:
            is_extrame = False

        return state, ini_prev_actions, self.current_date, is_extrame
        # return ini_prev_actions, self.current_date, state

    def test_reset(self, day_number):
        self.time_step = 0
        self.storage_charging_period = []
        self.storage_charging_time = 0
        # 这个是干嘛的？
        # self.storage_energy_used = 0
        self.storage_soc = 0.8  # 假设储能系统的起始SOC为80%
        # self.actions_history = []  # 历史动作记录
        # self.cost_history = []  # 储存每个时段的成本累积
        self.storage_price = 0.3688
        self.bus_charging_time = [0] * self.num_buses
        self.bus_charging_periods = [[] for _ in range(self.num_buses)]
        self.finished_trips = {i: [] for i in range(1, self.num_buses + 1)}
        self.bus_soc = [0.8] * self.num_buses  # 假设每辆公交车的起始SOC为80%
        self.bus_soc_ini = [0.8] * self.num_buses  # 假设每辆公交车的起始SOC为80%
        self.charging_gain = [0.0] * self.num_buses  # 耗能只能一起算所以充电量也要一起算
        action_ini, storge_action_ini = self.reset_action()
        ini_prev_actions = (action_ini, storge_action_ini)
        self.day_index = test_day_list[day_number]  # 用于测试
        # self.day_index = day_list_add[day_number]  # 用于补充训练
        # self.day_index = day_number  #  用于训练
        self.current_date = self.base_date + timedelta(days=self.day_index - 1)
        # 这个是用来生成发车时间的
        self.timetables = self.generate_timetables()
        # 确定每辆车所跑的班次编号
        self.vehicle_schedules = self.assign_trips_to_buses()

        # 更清晰的看到各线路各车辆的班次信息
        self.schedules = self.unify_bus_numbers()
        # 获取当日的天气信息便于后续的处理
        self.daily_data = self.weather_df[self.weather_df['datetime'].dt.date == self.current_date.date()]
        # 生成每个班次的信息，包含开始时间结束时间、平均温度、光照强度等
        self.trip_weather_info = self.get_trip_weather_info()

        self.route_average_consumptiomn = self.calculate_average_energy_per_route(self.trip_weather_info)
        # # 获得初始状态
        state = self.get_current_state(action_ini, storge_action_ini, storge_charge_energy = 0)

        self.sg_price = self.get_grid_price()


        if self.day_index in extrame_list:
            is_extrame = True
        else:
            is_extrame = False

        return state, ini_prev_actions, self.current_date, is_extrame
        # return ini_prev_actions, self.current_date, state


    def reset_action(self):
        # 初始化环境状态
        action_ini = [0 for _ in range(self.num_buses)]
        storge_action_ini = 0
        return action_ini, storge_action_ini


    def generate_timetables(self):
        all_routes_schedule = {}
        for route_name, details in self.line_periods.items():
            all_routes_schedule[route_name] = self.generate_full_day_schedule_min(details, self.line_timing_details[
                route_name])
        return all_routes_schedule


    def generate_full_day_schedule_min(self, route_details, timing):
        full_schedule = []
        for period_type, periods in route_details.items():
            interval = timing[period_type]["interval"]
            for start, end in periods:
                current_time = datetime.strptime(start, '%H:%M')
                end_time = datetime.strptime(end, '%H:%M')
                while current_time < end_time:
                    minutes_since_midnight = current_time.hour * 60 + current_time.minute
                    full_schedule.append(minutes_since_midnight)
                    current_time += timedelta(minutes=interval)
        return sorted(set(full_schedule))


    def assign_trips_to_buses(self):
        """
        根据每条线路的公交车数，为各公交车分配班次编号。

        返回:
            dict: 各线路公交车的班次编号分配。
        """
        vehicle_schedules = {}
        for route_name, num_buses in self.num_buses_per_line.items():
            # 获取该线路的所有班次时间
            route_schedule = self.timetables.get(route_name, [])
            # 创建列表，为每辆公交车分配班次编号
            bus_schedules = [[] for _ in range(num_buses)]
            # 分配班次编号给公交车
            for i, trip_time in enumerate(route_schedule):
                bus_index = i % num_buses
                # 存储班次编号，而不是时间
                bus_schedules[bus_index].append(i + 1)  # 使用班次的索引作为班次编号，假设从1开始编号
            # 保存该线路的公交车班次编号分配
            vehicle_schedules[route_name] = bus_schedules

        return vehicle_schedules


    def unify_bus_numbers(self):
        unified_bus_schedule = {}
        bus_index_global = 1  # 用于统一编号的全局索引

        for route_name, schedules in self.vehicle_schedules.items():
            for local_index, schedule in enumerate(schedules):
                # 包含在原线路中的编号以及其它信息
                unified_bus_schedule[bus_index_global] = {
                    'route': route_name,
                    'trips': schedule,
                    'local_index': local_index + 1  # 本地编号（在原线路中的编号）
                }
                bus_index_global += 1  # 更新全局索引

        return unified_bus_schedule


    def minutes_to_time(self, minutes):
        """Convert minutes since midnight into formatted time string."""
        hours = minutes // 60
        minutes = minutes % 60
        return f"{hours:02}:{minutes:02}"


    def adjust_time_format(self, time_str):
        # 分割时、分、秒
        hours, minutes, seconds = time_str.split(':')
        # 去除小时数前的零，注意如果小时数为 "00"，则不去除
        adjusted_hour = str(int(hours))  # int转换自动去除前导零，再转回字符串
        # 组合回完整的时间格式，保持分钟和秒不变
        adjusted_time = f"{adjusted_hour}:{minutes}:{seconds}"
        return adjusted_time


    def get_trip_weather_info(self):
        trip_weather_info = {}

        for route, schedule in self.timetables.items():
            trip_id = 1  # 初始化班次编号
            trip_weather_info[route] = []
            route_length = self.mileage[route]
            for start_minutes in schedule:
                start_time_formatted = self.minutes_to_time(start_minutes)
                start_datetime = datetime.combine(self.current_date,
                                                  datetime.strptime(start_time_formatted, '%H:%M').time())
                trip_periods = {}  # 存储行程穿越的每个时段及其持续时间

                # 判断当前班次的起始时间属于哪个时段，并获取该时段的行程时间和方差
                current_period = None
                for period, times in self.line_periods[route].items():
                    for time_range in times:
                        start_period = datetime.strptime(time_range[0], '%H:%M').time()
                        end_period = datetime.strptime(time_range[1], '%H:%M').time()
                        if start_period <= start_datetime.time() <= end_period:
                            current_period = period
                            break
                    if current_period:
                        break

                if current_period:
                    average_time = self.line_timing_details[route][current_period]['average_travel_time']
                    variance = self.line_timing_details[route][current_period]['variance']
                else:
                    # 默认值，如果没有匹配的时段
                    average_time = 45  # 可以设置为该线路的平均行程时间
                    variance = 10  # 默认方差

                # 生成行程时间
                duration = max(1, int(np.random.normal(average_time, np.sqrt(variance))))

                end_datetime = start_datetime + timedelta(minutes=duration)

                # 计算行程期间每分钟的环境状态
                current_time = start_datetime
                environmental_data = {'temperature': [], 'humidity': [], 'precipitation': [],
                                      'Horizontal_hradiation': []}
                while current_time <= end_datetime:
                    hour_string = current_time.strftime('%H:00:00')
                    hour_string_change = self.adjust_time_format(hour_string)
                    minute_data = self.daily_data[self.daily_data['time'] == hour_string_change]
                    if not minute_data.empty:
                        environmental_data['temperature'].append(minute_data['temperature'].iloc[0])
                        environmental_data['humidity'].append(minute_data['humidity'].iloc[0])
                        environmental_data['precipitation'].append(minute_data['precipitation'].iloc[0])
                        environmental_data['Horizontal_hradiation'].append(
                            minute_data['Horizontal_hradiation'].iloc[0])
                    current_time += timedelta(minutes=1)

                # 计算平均环境状态
                average_environmental_states = {}
                for key in environmental_data:
                    if environmental_data[key]:
                        average_environmental_states[key] = sum(environmental_data[key]) / len(
                            environmental_data[key])
                    else:
                        average_environmental_states[key] = None  # 如果没有数据，设为 None

                # 计算平均环境状态和能耗
                avg_temp = average_environmental_states.get('temperature',
                                                            self.optimal_temperature)  # Use default temp if not available
                energy_consumption = self.calculate_energy_consumption(route_length, average_time, avg_temp)

                # 将数据和编号添加到信息中
                trip_weather_info[route].append({
                    'trip_id': trip_id,
                    'start_time': start_datetime,
                    'end_time': end_datetime,
                    'duration': duration,
                    'average_environmental_states': average_environmental_states,
                    'energy_consumption': energy_consumption  # Add energy consumption here
                })
                trip_id += 1  # 更新班次编号

        return trip_weather_info


    def calculate_energy_consumption(self, length, travel_time, avg_temp):
        ln_L_n = np.log(length)
        ln_F_k = np.log(self.bus_mass)
        ln_T_n = np.log(travel_time)
        abs_temp_diff = np.abs(avg_temp - self.optimal_temperature)
        ln_E_kn = -8.11 + 0.5523 * ln_L_n + 0.78 * ln_F_k + 0.35 * ln_T_n + 0.0077 * abs_temp_diff
        E_kn = np.exp(ln_E_kn)
        return E_kn


    def calculate_average_energy_per_route(self, trip_weather_info_input):
        route_energy_totals = {}
        route_trip_counts = {}

        for route, trips in trip_weather_info_input.items():
            total_energy = 0
            trip_count = 0

            for trip in trips:
                if 'energy_consumption' in trip:
                    total_energy += trip['energy_consumption']
                    trip_count += 1

            if trip_count > 0:
                route_energy_totals[route] = total_energy
                route_trip_counts[route] = trip_count

        average_energy_per_route = {}
        for route in route_energy_totals:
            average_energy_per_route[route] = route_energy_totals[route] / route_trip_counts[route]

        return average_energy_per_route


    def get_bus_trip_status(self):
        current_datetime = self.step_to_datetime(self.time_step)  # 获取当前时间
        trip_status = {}  # 存储每辆公交车的状态

        for agent_id, agent_info in self.schedules.items():
            # print("self.schedules", self.schedules)
            # print("当前agent从几号开始", agent_id)
            route_name = agent_info['route']
            bus_index = agent_info['local_index']
            trips = agent_info['trips']

            current_trip_id = None
            is_departing_now = False
            time_to_next_departure = 10000
            average_e = self.route_average_consumptiomn[route_name]

            for trip_index in trips:
                # print("fsasdfhohoehyfioewhioewfioew   route_name", route_name)
                trip_info = self.get_specific_trip_info(route_name, bus_index, trip_index)

                start_time = trip_info['start_time']
                end_time = trip_info['end_time']

                if current_datetime == start_time:
                    is_departing_now = True

                if (start_time - timedelta(seconds=1)) <= current_datetime <= (end_time + timedelta(seconds=1)):
                    current_trip_id = trip_index
                    # 找到当前班次后，继续寻找下一个班次的开始时间
                    for future_trip_index in trips[trips.index(trip_index) + 1:]:
                        future_trip_info = self.get_specific_trip_info(route_name, bus_index,
                                                                                  future_trip_index)
                        next_trip_start_time = future_trip_info['start_time']
                        time_to_next_departure = (next_trip_start_time - current_datetime).total_seconds() / 60
                        break
                    break
                elif current_datetime < start_time:
                    time_to_next_departure = (start_time - current_datetime).total_seconds() / 60  # 转换为分钟
                    break

            trip_status[agent_id] = {
                'current_trip_id': current_trip_id,
                'is_departing_soon': is_departing_now,
                "time_to_next_departure": time_to_next_departure,
                "average_e": average_e
            }

        return trip_status


    def step_to_datetime(self, step):
        """Converts a time step into a datetime object starting from 6:00 of the current date."""
        return self.current_date + timedelta(hours=6, minutes=step)


    def get_specific_trip_info(self, route_name, bus_index, trip_index):
        """
        获取指定线路、指定公交车的特定班次信息。

        参数:
            route_name (str): 线路名称，如 "Route 1"
            bus_index (int): 公交车编号，从1开始
            trip_index (int): 班次编号，从1开始

        返回:
            dict: 特定班次的详细信息
        """
        # 首先确认线路名称、公交车编号和班次编号都在有效范围内
        weather_info = self.trip_weather_info


        # 从 weather_info 中获取对应的班次信息
        trips = weather_info[route_name]
        for trip in trips:
            if trip['trip_id'] == trip_index:  # 使用班次编号进行匹配
                return trip

        return f"No trip information available for Trip {trip_index} on Bus {bus_index} on {route_name}"


    def get_current_state(self, bus_actions, storage_action, storge_charge_energy):
        """
        获取当前时刻的状态，包括环境状态、公交车智能体状态和储能智能体状态。

        :param bus_actions: 上一时段的公交车智能体动作
        :param storage_action: 上一时段的储能智能体动作
        :return: 当前步长的状态字典
        """

        horizontal_irradiation, temperature = self.get_current_weather()

        # 更新SOC和充电时间
        self.update_charging_times(bus_actions, storage_action)
        # 更新充电记录
        self.update_charging_periods()
        self.update_completed_trips()  # 更新智能体已完成的班次

        self.update_soc(bus_actions, storage_action, storge_charge_energy)

        # 获取环境状态

        pv_power = self.calculate_pv_power(horizontal_irradiation, temperature)
        grid_price = self.get_grid_price()
        ess_price = self.update_ess_unit_price(storage_action, storge_charge_energy)  # 假设这是之前计算或更新过的

        # 环境状态
        environment_state = {
            'temperature': temperature,
            'horizontal_irradiation': horizontal_irradiation,
            'pv_power': pv_power,
            'grid_price': grid_price,
            'ess_price': ess_price
        }

        # 公交车智能体状态
        bus_states = []
        self.trip_status = self.get_bus_trip_status()
        for i in range(len(bus_actions)):
            bus_state = {
                'current_trip': self.trip_status[i+1]['current_trip_id'],
                'is_departing_soon': self.trip_status[i+1]['is_departing_soon'],
                'time_to_next_departure': self.trip_status[i+1]['time_to_next_departure'],
                'average_e': self.trip_status[i + 1]['average_e'],
                'soc': self.bus_soc[i],
                'continuous_charging_time': self.bus_charging_time[i]
            }
            bus_states.append(bus_state)

        # 储能智能体状态
        storage_state = {
            'soc': self.storage_soc,
            'continuous_charging_time': self.storage_charging_time
        }

        # 组合所有状态信息
        current_state = {
            'environment': environment_state,
            'buses': bus_states,
            'storage': storage_state
        }

        return current_state


    def update_charging_times(self, bus_actions, storage_action):
        # 更新公交车的累计充电时间
        for i in range(self.num_buses):
            if bus_actions[i] != 0:  # 如果当前动作是充电（不管使用什么方式）
                self.bus_charging_time[i] += 1  # 增加累计充电时间
            else:
                self.bus_charging_time[i] = 0  # 重置充电时间

        # 更新储能设备的累计充电时间
        if storage_action != 0:
            self.storage_charging_time += 1
        else:
            self.storage_charging_time = 0
        return


    def update_charging_periods(self):
        # 更新每个公交车和储能设备的每次充电周期的累计时间
        for i in range(self.num_buses):
            if self.bus_charging_time[i] > 0:
                if self.bus_charging_periods[i] and self.bus_charging_periods[i][-1]['end_time'] is None:
                    self.bus_charging_periods[i][-1]['duration'] += 1
                else:
                    self.bus_charging_periods[i].append({'start_time': self.time_step, 'end_time': None, 'duration': 1})
            elif self.bus_charging_periods[i] and self.bus_charging_periods[i][-1]['end_time'] is None:
                self.bus_charging_periods[i][-1]['end_time'] = self.time_step - 1

        if self.storage_charging_time > 0:
            if self.storage_charging_period and self.storage_charging_period[-1]['end_time'] is None:
                self.storage_charging_period[-1]['duration'] += 1
            else:
                self.storage_charging_period.append({'start_time': self.time_step, 'end_time': None, 'duration': 1})
        elif self.storage_charging_period and self.storage_charging_period[-1]['end_time'] is None:
            self.storage_charging_period[-1]['end_time'] = self.time_step - 1


    def update_completed_trips(self):
        current_datetime = self.step_to_datetime(self.time_step)  # 使用当天日期和当前步骤计算实际时间
        for agent_id, agent_info in self.schedules.items():
            route_name = agent_info['route']
            bus_index = agent_info['local_index']
            completed_trips = []
            for trip_index in agent_info['trips']:
                trip_info_get = self.get_specific_trip_info(route_name, bus_index, trip_index)
                if trip_info_get['end_time'] <= current_datetime:
                    completed_trips.append(trip_index)
            self.finished_trips[agent_id] = completed_trips


    def update_soc(self, bus_actions, storage_action, storge_charge_energy):
        """更新公交车和储能设备的SOC"""
        # 更新公交车的SOC
        for i in range(self.num_buses):
            if not self.finished_trips.get(i+1, []):  # 检查字典中键 i 是否存在，若不存在则返回空列表
                energy_used = 0
            # 计算公交车在已完成的班次中使用的总能量
            else:
                energy_used = 0
                if i < 8:
                    route_name = 'Route 1'
                elif i < 17:
                    route_name = 'Route 2'
                else:
                    route_name = 'Route 3'
                # for trip in self.finished_trips[i]:
                #     trip = self.get_specific_trip_info()
                # print("出现问题调试步骤0  i route_name", i, route_name)
                for trip in self.finished_trips[i+1]:
                    trip1 = self.get_specific_trip_info(route_name, i+1, trip)
                    distance = self.mileage[route_name]
                    # print("出现问题调试步骤1  self.finished_trips[i]", self.finished_trips[i])
                    # print("出现问题调试步骤2  trip", trip)
                    # print("出现问题调试步骤3  trip1", trip1)
                    time = trip1['duration']
                    temperature = trip1['average_environmental_states']['temperature']
                    energy_used += self.calculate_trip_energy(distance,time,temperature)

            # 计算充电所获得的能量
            if bus_actions[i] != 0:
                self.charging_gain[i] +=  self.P_CP * self.charging_efficiency / 60
                # charging_gain = self.P_CP * self.charging_efficiency / 60
            else:
                self.charging_gain[i] +=  0
                # charging_gain = 0

            # 更新SOC，考虑到电池容量和健康状态
            self.bus_soc[i] = self.bus_soc_ini[i] - ((energy_used - self.charging_gain[i]) / (self.bus_capacity * self.bus_battery_SOH))
            # self.bus_soc[i] -= (energy_used - charging_gain) / (self.bus_capacity * self.bus_battery_SOH)
            # print(f"公交车编号: {i}, 电量: {self.bus_soc[i]:.2f} ")

        # 更新储能设备的SOC
        if storage_action != 0:
            if self.time_step < 720:
                storage_charging_gain = storge_charge_energy * self.charging_efficiency
            else:
                storage_charging_gain = self.P_CP * self.charging_efficiency / 60
        else:
            storage_charging_gain = 0

        # 计算使用储能进行充电的公交车数量
        num_buses_using_storage = bus_actions.count(2)
        # 计算储能设备的总输出功率
        current_discharge_energy = num_buses_using_storage * self.P_CP / 60

        # 更新储能设备的SOC
        # print("出现问题 (current_discharge_energy - storage_charging_gain)", ((current_discharge_energy - storage_charging_gain) / (
        #             self.storage_capacity * self.storage_battery_SOH)))
        aaa  = ((current_discharge_energy - storage_charging_gain) / (self.storage_capacity * self.storage_battery_SOH))
        # print("储能soc变化有问题", "储能用电量", current_discharge_energy, "储能充电量", storage_charging_gain, "当前soc变化量", aaa,  "变化前soc", self.storage_soc)
        self.storage_soc -= aaa
        # print("变化后soc",self.storage_soc)
        # print(print(f"储能装置, 电量: {self.storage_soc:.2f} "))


    def get_current_weather(self):
        """获取当前时段的环境温度和水平方向的辐射强度"""
        # 将时间步转换为datetime对象
        current_datetime = self.step_to_datetime(self.time_step)
        # 获取当前小时数，以便从weather字典中提取数据
        current_hour = current_datetime.strftime('%H:00:00')
        current_hour_change = self.adjust_time_format(current_hour)

        # 从weather字典中获取对应小时的环境信息
        current_weather = self.daily_data[self.daily_data['time'] == current_hour_change]
        # current_weather = self.weather_df.get(current_hour_change, None)
        if current_weather is not None:
            temperature = current_weather.get('temperature', 'No data')
            horizontal_irradiation = current_weather.get('Horizontal_hradiation', 'No data')
            return horizontal_irradiation.iloc[0], temperature.iloc[0]
        else:
            return 'No data', 'No data'


    def calculate_pv_power(self, gt, temp_amb):
        pv_area_unit = 1.63
        """
        计算时段t的光伏系统发电功率

        :param self.pv_efficiency: 光伏发电效率 0.95
        :param self.pv_capacity: 光伏额定功率, kW 263
        :param gt: 时段t的太阳辐射量
        :param self.pv_area: 光伏面积, m^2  1304
        :param self.temperature_coefficient: 温度系数, 1/°C  0.0045
        :param self.pv_reference_temperature: 光伏电池的参考温度, °C  25
        :param temp_amb: 环境温度, °C
        :param self.pv_normal_operating_temperature : 光伏电池正常工作条件下的温度, °C  55
        :return: 时段t的光伏发电功率, kW
        """
        # 计算光伏电池的温度
        temp_cell = temp_amb + (self.pv_normal_operating_temperature - 20) * (gt / 800)
        self.capacity = self.pv_area / pv_area_unit * self.pv_capacity
        # 计算发电功率
        pv_power = self.pv_efficiency * self.capacity * (gt / 1000) * (
                    1 - self.temperature_coefficient * (temp_cell - self.pv_reference_temperature)) / 60

        return pv_power


    def get_grid_price(self):
        """
        获取给定时段的国家电网电价
        :return: 当前时段的电网电价
        """
        # 将时间步转换为datetime对象
        current_datetime = self.step_to_datetime(self.time_step)
        # 获取当前小时数，以便从weather字典中提取数据
        current_hour = current_datetime.strftime('%H:00:00')
        # 直接从grid字典中获取当前时段的电价
        price = self.grid[current_hour]['price']
        if price is None:
            print("电价信息不可用或未定义")
        else:
            # print('当前时刻',current_datetime, price)
            self.sg_price = price
            return price


    def update_ess_unit_price(self, storage_action, storge_charge_energy):
        """
        根据给定参数计算当前时段的储能单价。
        """
        # 计算前一个时段的电量
        E_t_minus_1 = self.storage_soc * self.storage_battery_SOH * self.storage_capacity
        total_cost = self.storage_price * E_t_minus_1
        total_energy = E_t_minus_1
        # 光伏充电
        if storage_action != 0:
            if self.time_step < 900:
                total_cost += self.pv_price * storge_charge_energy  # cp/60 转换为kWh
                total_energy += storge_charge_energy * self.charging_efficiency
            else:
                grid_price = self.get_grid_price()
                total_cost += grid_price * (self.P_CP / 60)
                total_energy += (self.P_CP / 60) * self.charging_efficiency
        # 更新储能设备的状态和价格
        current_ess_price = total_cost / total_energy
        self.storage_price = current_ess_price
        return current_ess_price


    def step(self, imi_state, ini_prev_actions, bus_actions, storage_action, current_episode):
        # 动态调整权重，随着时间步的增加逐步降低惩罚权重
        violate_constraint = 0

        # 获得环境状态
        gt = imi_state['environment']['horizontal_irradiation']
        k_env = imi_state['environment']['temperature']

        '''0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'''
        # peak_stage_charing = [i for i, x in enumerate(bus_actions) if x != 0]
        # # print(self.time_step, "原始网络输出需要充电的车",  peak_stage_charing, '共', len(peak_stage_charing),'个取值不为0')
        # print(self.time_step, "原始网络输出 储能", storage_action)

        # 行驶车辆动作置零 + 预处理
        '''
        driving_bus_ids, charging_bus_ids, bus_actions, storage_action, bus_soc_max_arrive, storge_soc_max_arrive
        '''
        (bus_actions_index, charging_bus_ids, pre_bus_actions,
         pre_storage_action, bus_soc_max_arrive, storge_soc_max_arrive, soc_min_ids, soc_min_ids_1) = self.set_driving_buses_to_no_charge(imi_state, bus_actions, storage_action, ini_prev_actions[0], ini_prev_actions[1])

        '''0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'''
        # peak_stage_charing = [i for i, x in enumerate(bus_actions) if x != 0]
        # # print(self.time_step,"预处理部分动作变为1后需要充电的车",  peak_stage_charing )
        #
        # print(self.time_step, "预处理储能", storage_action)

                # 违反约束个数(充电时间长度)
        if pre_storage_action != storage_action:
            violate_constraint += 1
        if pre_bus_actions != bus_actions:
            violate_constraint += 1

        # 处理正在运行的车辆以及充电时间不够的车辆
        post_bus_actions = self.reset_bus_actions(pre_bus_actions, bus_actions_index)

        '''0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'''
        # print("不能充电的公交车集合", bus_actions_index)
        # peak_stage_charing = [i for i, x in enumerate(bus_actions) if x != 0]
        # # if len(peak_stage_charing) != 0:
        # #     for i in peak_stage_charing:
        # #         print("实际充电的车", i, '动作', post_bus_actions[i])
        # print(self.time_step,"行驶动作变0后可以充电的车", peak_stage_charing )


        # 后处理动作
        '''
        bus_actions, storage_action, pv_supply, pv_power, storge_charg_energy
        '''
        fina_bus_actions, fina_storage_action, pv_supply, pv_power, storge_charge_energy = self.post_process_actions(post_bus_actions, pre_storage_action, gt, k_env,
                                                                          ini_prev_actions[0], charging_bus_ids, soc_min_ids, bus_actions_index)

        '''0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'''
        # peak_stage_charing = [i for i, x in enumerate(fina_bus_actions) if x != 0]
        # print(self.time_step, "后处理后需要充电的车", peak_stage_charing,  '共', len(peak_stage_charing),'个取值不为0' )
        # if len(peak_stage_charing) != 0:
        #     for i in peak_stage_charing:
        #         print("车", i, '动作', fina_bus_actions[i])
        # print(self.time_step, "后处理储能", fina_storage_action)

        # 处理电量已经在80%的储能
        if storge_soc_max_arrive:
            # print("储能SOC是满的，对应动作将归零", storage_action)
            fina_storage_action = 0
            storge_charge_energy = 0

        # 处理电量已经在80%的车辆
        fina_bus_actions = self.reset_bus_actions(fina_bus_actions, bus_soc_max_arrive)

        '''0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'''
        # peak_stage_charing = [i for i, x in enumerate(fina_bus_actions) if x != 0]
        #
        # print(self.time_step, "SOC最大值处理后需要充的车",  peak_stage_charing, '共', len(peak_stage_charing),'个取值不为0' )
        # if len(peak_stage_charing) != 0:
        #     for i in peak_stage_charing:
        #         print("车", i, '动作', fina_bus_actions[i])
        # print(self.time_step, "SOC最大值处理储能", fina_storage_action)

        if self.time_step > 900:
            count = sum(1 for element in fina_bus_actions if element != 0)
            result = [i for i in range(24) if i not in bus_soc_max_arrive]
            fina_bus_actions = [0] * 24
            # m = self.charging_station_number - count  # 这里假设m的值为5，你可以按需修改
            m = self.charging_station_number
            charging_new = result[:m]

            for i in charging_new:
                fina_bus_actions[i] = 3

            # print("夜晚的最终count", count, "当前动集合", fina_bus_actions)
            if fina_storage_action == 0 and self.storage_soc < self.storage_battery_max_soc:
                fina_storage_action = 1


        # 违反约束个数(后处理)
        if pre_storage_action != fina_storage_action:
            violate_constraint += 1
        if pre_bus_actions != post_bus_actions:
            violate_constraint += 1

        pv_supply = self.calculate_pv_supply(fina_bus_actions, fina_storage_action, storge_charge_energy)
        if pv_power == 0:
            PV_SELF_USE = 0
        elif 0 < ((pv_supply-storge_charge_energy) / pv_power) < 1:
            PV_SELF_USE = 5 *((pv_supply-storge_charge_energy) / pv_power) + storge_charge_energy / pv_power
        else:
            PV_SELF_USE = 0

        '''0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'''
        # peak_stage_charing = [i for i, x in enumerate(fina_bus_actions) if x != 0]
        #
        # print(self.time_step, "输入计算奖励1的车",  peak_stage_charing, '共', len(peak_stage_charing),'个取值不为0')
        # print(self.time_step, "输入计算奖励1的 储能动作", fina_storage_action)


        reward1 = self.compute_total_charging_cost(fina_bus_actions, fina_storage_action, storge_charge_energy)
        reward2 = self.compute_total_carbon_emission(fina_bus_actions, fina_storage_action, storge_charge_energy)
        # 执行动作改变状态
        self.time_step += 1  # 增加时间步
        state = self.get_current_state(fina_bus_actions, fina_storage_action, storge_charge_energy)
        # 计算奖励

        if self.storage_price < self.sg_price and  pv_power < 0.65 and self.storage_soc >0.21:
            ess_supply = self.calculate_ess_supply(fina_bus_actions)
            ess_use = ess_supply / ((self.P_CP / 60) * 3) * 2
        else:
            ess_use = 0

        peak_charing_reward = 0
        if self.sg_price > self.storage_price:
            peak_stage_charing = [i for i, x in enumerate(bus_actions) if x == 3]
            if len(peak_stage_charing) != 0:
                peak_charing_reward = 1

        reward_3 = self.calculate_penalty(state)
        # if reward_3 > 0:
        #     print(self.bus_soc)
        #     print(fina_bus_actions)
        #     print(soc_min_ids)
        #     print(soc_min_ids_1)
        #     print(bus_actions_index)

        reward_4 = self.calucalat_night_charge_rewaqrd(state)

        reward_1 = -(reward1 + reward_3 + peak_charing_reward) + reward_4 + PV_SELF_USE + ess_use
        reward_2 = -(reward2 + reward_3 + peak_charing_reward) + reward_4 + PV_SELF_USE + ess_use

        # print("reward1, reward_3, peak_charing_reward, reward_4, PV_SELF_USE, ess_use", reward1, reward_3, peak_charing_reward, reward_4, PV_SELF_USE, ess_use)

        if 0 < self.time_step < 0:
            print("步长", self.time_step, "成本", reward1, "碳排", reward2, "惩罚函数",
                  reward_3, '综合r1', reward_1, '综合r2', reward_2,
                  "公交车光", pv_supply - storge_charge_energy, "储能光%", storge_charge_energy,
                  "储能动作", fina_storage_action, "储能soc", self.storage_soc,
                  "光功率", pv_power * 60)

        # for i in range(self.num_buses):
        #     print(i, self.bus_charging_periods[i])
        # if 1420 < self.time_step < 1440:
        #     print("步长", self.time_step, "成本", reward1, "碳排", reward2, "惩罚函数",
        #           reward_3, '综合r1', reward_1, '综合r2', reward_2,
        #           "公交车光", pv_supply - storge_charge_energy, "储能光%", storge_charge_energy,
        #           "储能动作", fina_storage_action, "储能soc", self.storage_soc,
        #           "光功率", pv_power * 60)

        # if self.time_step == 1081:
        # peak_stage_charing = [i for i, x in enumerate(bus_actions) if x != 0]
        # print(peak_stage_charing)

        if self.time_step == 1440:
            done = True
            charging_fee = 0
            for i in range(self.num_buses):
                if self.bus_soc[i] < self.bus_max_soc:
                    # print("self.bus_soc[i]", self.bus_soc[i])
                    charging_fee1 = 0.3688 * (self.bus_max_soc - self.bus_soc[i]) * (
                                self.bus_capacity * self.bus_battery_SOH)
                    charging_fee += charging_fee1
                    # print("公交车",i,"还需要继续充电,充电费用是", charging_fee1)
            if self.storage_soc < self.storage_battery_max_soc:
                charging_fee2 = 0.3688 * (self.storage_battery_max_soc - self.storage_soc) * (
                            self.storage_capacity * self.storage_battery_SOH)
                charging_fee += charging_fee2
                # print("储能装置还需要继续充电，充电费用是", charging_fee2)
        else:
            done = False
            charging_fee = 0

        return state, reward1, reward2, reward_3, reward_1, reward_2, done, charging_fee, fina_bus_actions, fina_storage_action, violate_constraint, pv_supply, storge_charge_energy, pv_power, reward_4


    def update_constraint_penalty(self,current_episode):
        '''
        self.w13 = 1 w23 = 0.01 的时候对应的reward3是与reward1和reward2一致大小的
        :param current_episode:
        :param total_training_episodes:
        :return:
        '''
        # 计算当前训练的百分比
        total_training_episodes = 500
        training_percentage = current_episode / total_training_episodes

        # 前期阶段：前 20% 的训练
        if training_percentage <= 0.2:
            constraint_penalty_weight_1 = 20  # 强化约束，设置较高的惩罚权重
            constraint_penalty_weight_2 = 0.2  # 强化约束，设置较高的惩罚权重

        # 中期阶段：20% - 50% 之间，逐步降低权重
        elif 0.2 < training_percentage <= 0.5:
            # 使用插值方式逐步降低权重
            constraint_penalty_weight_1 = 20 * (1 - (training_percentage - 0.2) / 0.3)
            constraint_penalty_weight_2 = 0.2 * (1 - (training_percentage - 0.2) / 0.3)

        # 后期阶段：50% - 100% 之间，固定权重
        else:
            constraint_penalty_weight_1 = 0.5 # 在最后阶段，固定一个较低的权重
            constraint_penalty_weight_2 = 0.05 # 在最后阶段，固定一个较低的权重

        return constraint_penalty_weight_1, constraint_penalty_weight_2


    def set_driving_buses_to_no_charge(self, state, bus_actions, storage_action, pre_bus_actions, pre_storage_action):
        driving_bus_ids = []

        for i, bus in enumerate(state['buses']):
            # print("第941行的state的i从几号开始", i)  # 从0开始
            if bus['current_trip'] is not None:
                driving_bus_ids.append(i)
                # print(i, '正在行驶所以不能充电')
            elif pre_bus_actions[i] == 0 and bus['soc'] + (self.P_CP / 60 * (self.MIN_CHARGING_TIME + 1) * self.charging_efficiency) / (self.bus_capacity *self.bus_battery_SOH) >= self.bus_max_soc:
                driving_bus_ids.append(i)
                # print(i, '电量充足所以不能充电')
            elif pre_bus_actions[i] == 0:
                if bus['time_to_next_departure'] <= self.MIN_CHARGING_TIME :
                    driving_bus_ids.append(i)
                    # print(i, '时间不够所以不能充电')
            elif pre_bus_actions != 0:
                if bus['time_to_next_departure'] == 1:
                    driving_bus_ids.append(i)
                    # print(i, '即将发车所以不能充电')


        bus_soc_max_arrive = [] # 公交车与储能满了都设置为80 满了就不冲
        storge_soc_max_arrive = False
        for i, bus in enumerate(state['buses']):
            # print("第941行的state的i从几号开始", i)  # 从0开始
            if bus['soc'] >= self.bus_max_soc:
                bus_soc_max_arrive.append(i)
        if state['storage']['soc'] >= self.storage_battery_max_soc:
            storge_soc_max_arrive = True


        soc_min_ids = []
        if self.time_step< 540 or self.time_step> 660:
            for i, bus in enumerate(state['buses']):
                # print("第941行的state的i从几号开始", i)  # 从0开始
                if bus['current_trip'] is None:
                    if bus['time_to_next_departure'] is not None and bus['time_to_next_departure'] != 100000:
                        if bus['soc'] - (bus['average_e'] + 2) / self.bus_capacity <= self.bus_min_soc:
                            soc_min_ids.append(i)
                            # print( bus['current_trip'], bus['time_to_next_departure'])
                    else:
                        if bus['soc'] <= self.bus_min_soc and self.sg_price < 0.5:
                            soc_min_ids.append(i)
        else:
            for i, bus in enumerate(state['buses']):
                # print("第941行的state的i从几号开始", i)  # 从0开始
                if bus['current_trip'] is None:
                    if bus['time_to_next_departure'] is not None and bus['time_to_next_departure'] != 100000:
                        if bus['soc'] - (bus['average_e'] + 20) / self.bus_capacity <= self.bus_min_soc:
                            soc_min_ids.append(i)
                            # print( bus['current_trip'], bus['time_to_next_departure'])
                    else:
                        if bus['soc'] <= self.bus_min_soc and self.sg_price < 0.5:
                            soc_min_ids.append(i)
            # print('需要充电的车', soc_min_ids)
                        # print(bus['current_trip'], bus['time_to_next_departure'])
        # if  770 < self.time_step < 800:
        #     for i, bus in enumerate(state['buses']):
        #         if i == 0:
        #             print('bus[current_trip]', bus['current_trip'])
        #             print(bus['time_to_next_departure'])
        #             print(bus['soc'] - (bus['average_e'] + 2) / self.bus_capacity)


        #
        # print("soc已经小于最小值的车", soc_min_ids)
        new_bus_actions = [num for num in soc_min_ids if num not in driving_bus_ids]
        # print("soc已经小于最小值的车但是不在行驶的车", new_bus_actions)


        charging_bus_ids = []
        for i in range(self.num_buses):
            if self.bus_charging_periods[i]:
                last_period = self.bus_charging_periods[i][-1]
                if last_period['end_time'] is None and \
                        (self.time_step - last_period['start_time']) < self.MIN_CHARGING_TIME:
                    # 如果动作为停止充电，但未满足最小充电时间，则强制继续充电
                    bus_actions[i] = 1  # 假设1为充电的动作代码
                    charging_bus_ids.append(i)
            if bus_actions[i] == 3:
                if self.sg_price > 0.5:
                    bus_actions[i] = 1
        # print('需要充电的公交车', charging_bus_ids)

                    # if self.time_step >1080:
                    #     print(" self.bus_charging_periods[i]", self.bus_charging_periods[i], "last_period", last_period)
                    # print(f"Bus {i + 1}: Forced to continue charging due to insufficient charging duration. "
                    #         f"Duration: {self.time_step - last_period['start_time']} < Required: {self.MIN_CHARGING_TIME}")
  # 检查储能设备的充电状态
        ess_charging_buses = [i for i, x in enumerate(pre_bus_actions) if x == 2]

        if storage_action == 0 and self.storage_charging_period:
            last_period = self.storage_charging_period[-1]
            if last_period['end_time'] is None and \
                    (self.time_step - last_period['start_time']) < self.MIN_CHARGING_TIME:
                # 如果储能设备的动作为停止充电，但未满足最小充电时间，则强制继续充电
                storage_action = 1  # 假设1为充电的动作代码

        if  720 <=  self.time_step <= 900:
            storage_action = 0

        if len(ess_charging_buses) != 0:
            self.ess_count += 1
            if self.ess_count == self.MIN_CHARGING_TIME:
                storage_action = 0
                self.ess_count = 0

        return driving_bus_ids, charging_bus_ids, bus_actions, storage_action, bus_soc_max_arrive, storge_soc_max_arrive, new_bus_actions, soc_min_ids

    def post_process_actions(self, bus_actions, storage_action, gt, temp_amb, prev_bus_actions, charging_bus_ids, soc_min_ids, drving_ids):

        F = sum(1 for action in bus_actions if action != 0)
        O = self.charging_station_number

        result_indices0 = list(set(charging_bus_ids + soc_min_ids))
        result_indices = result_indices0
        # print("必须充电的车", result_indices, '对应的充电方式', bus_actions, '此时储能', storage_action)
        # 步骤3：计算当前时段光伏总供电功率priority_buses
        charg_bus = [i for i, x in enumerate(bus_actions) if x != 0]
        precharg_bus = [i for i, x in enumerate(prev_bus_actions) if x != 0]
        storge_charg_energy = 0

        if F >= O:
            if len(precharg_bus) == 0:
                charging_bus_ids = []
            priority_buses = self.compute_priority(bus_actions, charging_bus_ids, soc_min_ids, drving_ids)
            bus_actions = np.where(np.isin(range(len(bus_actions)), priority_buses), bus_actions, 0).tolist()
        elif F == 1:
            if len(result_indices) != 0 and charg_bus not in result_indices:
                bus_add_change = np.random.choice(result_indices)
                bus_actions[bus_add_change] = 1
        elif F == 0:
            # print("这些都需要充电", result_indices)
            if len(result_indices) != 0:
                # print("需要充电啊，有的没电了", soc_min_ids, result_indices)
                if len(result_indices) == 1:
                    bus_add_change = np.random.choice(result_indices)
                    bus_actions[bus_add_change] = 1
                elif len(result_indices) >= 2:
                    two_random_numbers = np.random.choice(result_indices, size=2)
                    bus_actions[two_random_numbers[0]] = 1
                    bus_actions[two_random_numbers[1]] = 1
        if len(result_indices0) == 0:
            if self.storage_soc < 0.31:
                bus_actions = [0] * 24

      # 需要充电的车必须充电


        pv_power = self.calculate_pv_power(gt, temp_amb)

        t1 = time.time()
        if storage_action == 0:
            if self.ess_is_chaging <= self.MIN_CHARGING_TIME + 5:
                if self.storage_soc < 0.7 and pv_power > 0.65:
                    storage_action = 1
                    self.ess_is_chaging += 1
                    # print('储能由0改成1,此时充电次数', self.ess_is_chaging)
        else:
            if self.ess_is_chaging > self.MIN_CHARGING_TIME + 5:
                storage_action = 0
                self.ess_is_chaging = 0
            else:
                self.ess_is_chaging += 1
        pv_supply = self.calculate_pv_supply(bus_actions, storage_action, storge_charg_energy)
        t2 = time.time()
        # print('储能更改', t2 - t1)
        # print('更改后的储能', storage_action)

        t3 = time.time()

        charg_bus_sg = [i for i, x in enumerate(bus_actions) if x == 3]
        if len(charg_bus_sg) == 1:
            if pv_power - pv_supply > 1.3:
                bus_actions[charg_bus_sg] = 1
        elif len(charg_bus_sg) == 2:
            if pv_power - pv_supply > 1.3:
                bus_actions[charg_bus_sg[0]] = 1

        while pv_supply > pv_power:
            # print("正常进行1")
            if self.pv_price < self.sg_price:
                # print("进行第一步")
                # print("正常进行2")
                ess_unit_price = self.storage_price
                # 步骤6：比较储能供电单价和电网电价
                if ess_unit_price <= self.sg_price :
                    # print("正常进行3")
                    if storage_action == 1:
                        # print("正常进行4", storage_action)
                        if self.ess_is_chaging <= 1:
                            # print("正常进行5", storage_action)
                            storage_action = 0
                            self.ess_is_chaging = 0
                    if storage_action == 0:
                        # print("正常进行6")
                        non_charging_buses = np.where((np.array(prev_bus_actions) == 2) & (bus_actions == 1))[0]
                        if len(non_charging_buses) == 0:
                            # print("正常进行7")
                            non_charging_buses = [i for i, x in enumerate(bus_actions) if x == 1]
                        bus_to_change = np.random.choice(non_charging_buses)
                        bus_actions[bus_to_change] = 2
                        # 新步骤：计算当前时段储能装置的供电量
                        ess_supply = self.calculate_ess_supply(bus_actions)
                        E_t_minus_1 = self.storage_soc * self.storage_battery_SOH * self.storage_capacity
                        # print("正常进行71")
                        if (E_t_minus_1 - ess_supply) < self.storage_battery_min_soc * self.storage_battery_SOH * self.storage_capacity:
                            # print("正常进行81", bus_to_change)
                            if bus_to_change in result_indices:
                                bus_actions[bus_to_change] = 3
                                # print('必须充电 bus_to_change', bus_to_change, 'result_indices', result_indices)
                                # print("正常进行9")
                            else:
                                # print("正常进行9")
                                if self.sg_price < 0.5:
                                    # print("正常进行10")
                                    bus_actions[bus_to_change] = 3
                                else:
                                    if 420 < self.time_step < 660 and pv_power < 0.3 :
                                        bus_actions[bus_to_change] = 3
                                    else:
                                        bus_actions[bus_to_change] = 0
                                    # print("正常进行10")

                                # print('非必须充电 bus_to_change', bus_to_change)


                    else:
                        # print("正常进行6")
                        non_charging_buses = [i for i, x in enumerate(bus_actions) if x == 1]
                        bus_to_change = np.random.choice(non_charging_buses)
                        if bus_to_change in result_indices:
                            bus_actions[bus_to_change] = 3
                            # print("正常进行9")
                        else:
                            # print("正常进行9")
                            if self.sg_price < 0.5:
                                # print("正常进行10")
                                bus_actions[bus_to_change] = 3
                            else:
                                # print("正常进行10")
                                bus_actions[bus_to_change] = 0
                        pv_supply = self.calculate_pv_supply(bus_actions, storage_action, storge_charg_energy)
                        continue


                else:
                    # print("正常进行3")
                    # 步骤8：替换为电网充电
                    non_charging_buses = np.where((np.array(prev_bus_actions) == 3) & (bus_actions == 1))[0]
                    if len(non_charging_buses) == 0:
                        non_charging_buses = [i for i, x in enumerate(bus_actions) if x == 1]
                    bus_to_change = np.random.choice(non_charging_buses)
                    bus_actions[bus_to_change] = 3

            else:
                # print("正常进行3")
                # 步骤8：替换为电网充电
                non_charging_buses = np.where((np.array(prev_bus_actions) == 3) & (bus_actions == 1))[0]
                if len(non_charging_buses) == 0:
                    non_charging_buses = np.where(np.array(bus_actions) == 1)[0]
                bus_to_change = np.random.choice(non_charging_buses)
                bus_actions[bus_to_change] = 3

            # 重新计算光伏总供电功率

            pv_supply = self.calculate_pv_supply(bus_actions, storage_action, storge_charg_energy)
            # print('有更改', bus_actions)

        t4 = time.time()
        # print('光伏变换', t4 - t3)
        # print('光伏更改后的公交车', bus_actions)
        # 步骤9：检查储能用电情况并实现替换
        storge_charg_energy = 0

        ess_supply = self.calculate_ess_supply(bus_actions)
        E_t_minus_1 = self.storage_soc * self.storage_battery_SOH * self.storage_capacity

        t5 = time.time()
        while (E_t_minus_1 - ess_supply) <  self.storage_battery_min_soc  * self.storage_battery_SOH * self.storage_capacity:
            non_charging_buses_STORY = np.where((prev_bus_actions == 3) & (bus_actions == 2))[0]
            if len(non_charging_buses_STORY) == 0:
                non_charging_buses_STORY = [i for i, x in enumerate(bus_actions) if x == 2]
            bus_to_change_STORRY = np.random.choice(non_charging_buses_STORY)
            if bus_to_change_STORRY in result_indices:
                bus_actions[bus_to_change_STORRY] = 3
            else:
                if self.sg_price < 0.5:
                    bus_actions[bus_to_change_STORRY] = 3
                else:
                    bus_actions[bus_to_change_STORRY] = 0
            ess_supply = self.calculate_ess_supply(bus_actions)
        t6 = time.time()

        # print('储能单独变化', t6 - t5)
        # print('储能更改后的公交车', bus_actions)


        t7 = time.time()
        if bus_actions.count(2)!= 0:
            if 1 < self.ess_is_chaging <= self.MIN_CHARGING_TIME + 5:
                storage_action = 1
                self.ess_is_chaging += 1
                pv_supply = self.calculate_pv_supply(bus_actions, storage_action, storge_charg_energy)
                non_charging_buses_STORY = [i for i, x in enumerate(bus_actions) if x == 2]
                if pv_supply == 0 and pv_power > 2:
                    if len( non_charging_buses_STORY) == 1:
                        bus_to_change_STORRY = non_charging_buses_STORY[0]
                        bus_actions[bus_to_change_STORRY] = 1
                    elif len( non_charging_buses_STORY) == 2:
                        bus_to_change_STORRY1 = non_charging_buses_STORY[0]
                        bus_actions[bus_to_change_STORRY1] = 1
                        bus_to_change_STORRY2 = non_charging_buses_STORY[0]
                        bus_actions[bus_to_change_STORRY2] = 3
                    else:
                        bus_to_change_STORRY = np.random.choice(non_charging_buses_STORY)
                        bus_actions[bus_to_change_STORRY] = 1
                else:
                    if len( non_charging_buses_STORY) == 1:
                        bus_to_change_STORRY = non_charging_buses_STORY[0]
                        bus_actions[bus_to_change_STORRY] = 3
                    elif len( non_charging_buses_STORY) == 2:
                        bus_to_change_STORRY1 = non_charging_buses_STORY[0]
                        bus_actions[bus_to_change_STORRY1] = 3
                        bus_to_change_STORRY2 = non_charging_buses_STORY[0]
                        bus_actions[bus_to_change_STORRY2] = 3
                    else:
                        bus_to_change_STORRY = np.random.choice(non_charging_buses_STORY)
                        if self.sg_price < 0.5:
                            bus_actions[bus_to_change_STORRY] = 3
                        else:
                            bus_actions[bus_to_change_STORRY] = 0
                storge_charg_energy = pv_power - pv_supply
                pv_supply = self.calculate_pv_supply(bus_actions, storage_action, storge_charg_energy)
            else:
                storage_action = 0
                storge_charg_energy = 0
                self.ess_is_chaging = 0
        else:
            if (pv_power-pv_supply) > 0.5:
                storage_action = 1
                storge_charg_energy = pv_power - pv_supply
                self.ess_is_chaging += 1
                pv_supply = self.calculate_pv_supply(bus_actions, storage_action, storge_charg_energy)
            elif (pv_power-pv_supply) <= 0.33 and storage_action == 1:
                storage_action = 0
                storge_charg_energy = 0
                self.ess_is_chaging = 0
                pv_supply = self.calculate_pv_supply(bus_actions, storage_action, storge_charg_energy)
        t8 = time.time()
        # print('储能被充电处理', t8 - t7)
        # print('最终的储能', storage_action)

        F = sum(1 for action in bus_actions if action != 0)
        if F == 0 and storage_action == 0:
            if pv_power > 1.33:
                priority_buses = self.compute_priority(bus_actions, charging_bus_ids, soc_min_ids, drving_ids)
                bus_actions[priority_buses[0]] = 1
                pv_supply = self.calculate_pv_supply(bus_actions, storage_action, storge_charg_energy)

        return bus_actions, storage_action, pv_supply, pv_power, storge_charg_energy


    def reset_bus_actions(self, bus_actions, bus_actions_index):
        """
        将索引在 bus_actions_index 中的公交智能体的动作设置为 0。

        :param bus_actions: 一个列表，包含所有公交智能体的动作
        :param bus_actions_index: 一个列表，包含需要重置动作的公交智能体的索引
        """
        for index in bus_actions_index:
            bus_actions[index] = 0

        return bus_actions


    #  这个是在新状态更新之前计算，仅以动作为输入，所对应价格是该时段开始时刻的状态所对应的价格
    def compute_total_charging_cost1(self, bus_actions, storage_action, storge_charge_energy):
        total_cost = 0

        # 计算公交车的充电成本
        for action in bus_actions:
            if action == 1:
                total_cost += self.pv_price * self.P_CP / 60
            elif action == 2:
                total_cost += self.storage_price * self.P_CP / 60
            elif action == 3:
                total_cost += self.sg_price * self.P_CP / 60

        # 计算储能装置的充电成本
        if storage_action != 0:
            if self.time_step < 720:
                total_cost += self.pv_price * storge_charge_energy
            else:
                total_cost += self.sg_price * self.P_CP / 60


        return total_cost


    def compute_total_charging_cost(self, bus_actions, storage_action, storge_charge_energy):
        total_cost = 0
        if self.time_step < 900:
            # 计算公交车的充电成本
            for action in bus_actions:
                if action == 1:
                    total_cost += self.pv_price * self.P_CP / 60
                elif action == 2:
                    total_cost += self.storage_price * self.P_CP / 60
                elif action == 3:
                    total_cost += self.sg_price * self.P_CP / 60
            # print("公交车充电成本", total_cost)
            # 计算储能装置的充电成本
            if storage_action != 0:
                if self.time_step < 720:
                    total_cost += self.pv_price * storge_charge_energy
                else:
                    total_cost += self.sg_price * self.P_CP / 60
            # print("储能充电成本", total_cost)
        else:
            if storage_action != 0:
                total_cost += self.sg_price * self.P_CP / 60
            a_energy_need = 0
            a_night_charging_max = self.P_CP * 2 * 9
            for i in range(self.num_buses):
                a_energy_need += (self.bus_max_soc - self.bus_soc[i]) * self.bus_battery_SOH * self.bus_capacity
            # print('需要充电量',a_energy_need, '最大充电量', a_night_charging_max)
            if a_energy_need > a_night_charging_max:
                print("夜间充电时间不足还差",a_energy_need - a_night_charging_max)
                print('更改电价由',self.sg_price,'修改至', a_energy_need * self.sg_price / a_night_charging_max)
                self.sg_price = a_energy_need * self.sg_price / a_night_charging_max
            for action in bus_actions:
                if action != 0:
                    total_cost += self.sg_price * self.P_CP / 60
            # 计算储能装置的充电成本

        return total_cost

    def compute_total_carbon_emission(self, bus_actions, storage_action, storge_charge_energy):
        total_emission_pv = 0
        total_emission_sg = 0
        # 计算公交车的充电成本
        for action in bus_actions:
            if action == 1:
                total_emission_pv += self.pv_carbon_emission_factor * self.P_CP / 60
            elif action == 3:
                total_emission_sg += self.sg_carbon_emission_factor * self.P_CP / 60

        # 计算储能装置的充电成本
        if storage_action != 0:
            if self.time_step < 720:
                total_emission_pv += self.pv_carbon_emission_factor * storge_charge_energy

            else:
                total_emission_sg += self.sg_carbon_emission_factor * self.P_CP / 60


        # print("对应的充电动作为", bus_actions, storage_action)
        # print("充电排放是", total_emission_pv + total_emission_sg)
        return total_emission_pv + total_emission_sg


    def calculate_penalty(self, new_state):
        '''
        就是这里需要重新写
        '''
        total_penalty = 0
        self.coef2 = 300
        # 计算公交车智能体的罚函数
        for i in range(self.num_buses):
            bus_soc = new_state['buses'][i]['soc']
            current_trip = new_state['buses'][i]['current_trip']
            average_e = new_state['buses'][i]['average_e']
            in_traving = 0 if current_trip == 0 else 1
            bus_penalty = self.coef2 * max(0, self.bus_min_soc - (bus_soc - in_traving * (average_e / (self.bus_capacity * self.bus_battery_SOH))))
            total_penalty += bus_penalty
            # print("正值表示有公交车违反了soc_min约束", total_penalty)

        # 计算储能智能体的罚函数

        storage_soc = new_state['storage']['soc']

        storage_penalty = self.coef2 * max(0, self.storage_battery_min_soc - storage_soc)
        # print("正值表示储能违反了soc_min约束", storage_penalty)

        total_penalty += storage_penalty

        return total_penalty


    def calucalat_night_charge_rewaqrd(self, state):
        alpha = 0.1
        gamma = 1
        night_charge_rewaqrd = 0
        if self.time_step > 900:
            for i in range(self.num_buses):
                # if self.time_step == 1439:
                    # print("state['buses'][i]['soc']", state['buses'][i]['soc'])
                night_charge_rewaqrd += alpha * np.exp(gamma * (state['buses'][i]['soc'] - self.bus_max_soc))
            night_charge_rewaqrd += alpha * np.exp(gamma * (state['storage']['soc'] - self.storage_battery_max_soc))

        return night_charge_rewaqrd

    def compute_priority(self, bus_actions, charging_bus_ids, soc_min_ids, drving_ids):
        # 创建一个字典来存储需要计算优先级的公交车
        priorities = {}

        # 仅为动作值非零的公交车计算优先级
        for i in range(self.num_buses):
            SOC_t_k = self.bus_soc[i]
            g_t_wait_k = self.trip_status[i+1]['time_to_next_departure'] if self.trip_status[i+1]['time_to_next_departure'] is not None else 100000
            m_t_k = (self.bus_max_soc - SOC_t_k)
            priorities[i+1] = m_t_k


        large_value = 10000  # 可根据实际情况调整这个较大值
        for bus_id in charging_bus_ids:
            priorities[bus_id] = large_value

        middle_value = 9000  # 可根据实际情况调整这个较大值
        for bus_id in soc_min_ids:
            priorities[bus_id] = middle_value

        mini_value = -9000  # 可根据实际情况调整这个较大值
        for bus_id in drving_ids:
            priorities[bus_id] = mini_value
        # 对优先级从高到低排序，并获取前O名的公交车编号
        sorted_buses = sorted(priorities, key=priorities.get, reverse=True)


        top_buses = sorted_buses[:self.charging_station_number]

        return top_buses


    def calculate_pv_supply(self, bus_actions, storage_action,storge_charg_energy):
        """
        计算在t时段的光伏供电量

        :param bus_actions: 公交车智能体的动作列表，1表示使用光伏充电
        :param storage_action: 储能智能体的动作，1表示使用光伏进行充电
        :param self.P_CP : 充电桩充电功率
        :return: t时段的光伏供电量
        """
        # 计算使用光伏进行充电的公交车数量
        pv_charging_buses = bus_actions.count(1)

        # 计算储能设备是否使用光伏进行充电
        pv_charging_storage = 1 if storage_action == 1 else 0

        # 总的使用光伏充电的设备数量
        total_pv_charging_units = pv_charging_buses + pv_charging_storage

        # 如果有设备使用光伏充电，则计算分配给每个设备的光伏电量
        if total_pv_charging_units > 0:
            # 假设光伏电量平均分配给每个充电设备
            if storage_action == 1:
                pv_supply = pv_charging_buses * self.P_CP / 60 + storge_charg_energy
            else:
                pv_supply = pv_charging_buses * self.P_CP / 60
        else:
            # 如果没有设备使用光伏充电，则供电量为0
            pv_supply = 0

        return pv_supply


    def calculate_ess_supply(self, bus_actions):

        # 计算使用光伏进行充电的公交车数量
        pv_charging_buses = bus_actions.count(2)


        # 如果有设备使用光伏充电，则计算分配给每个设备的光伏电量
        if pv_charging_buses  > 0:
            # 假设光伏电量平均分配给每个充电设备
            pv_supply = pv_charging_buses * self.P_CP / 60
        else:
            # 如果没有设备使用光伏充电，则供电量为0
            pv_supply = 0

        return pv_supply\


    def state_to_tensor(self, state):
        '''
        env_batch 形状为 (batch_size, 5)，即 (2, 5)。
        buses_batch 形状为 (batch_size, num_buses, 6)，即 (2, 2, 6)。
        storage_batch 形状为 (batch_size, 2)，即 (2, 2)。
        global_batch 形状为 (batch_size, num_features)，具体的 num_features 取决于 buses_tensor 展开后的长度和其他特征的总和。

        :param state:
        :return:
        '''
        # 如果输入是单个state，将其包装在一个列表中
        if isinstance(state, dict):
            state = [state]

        # 初始化列表，用于存储每个state转换后的张量
        environment_tensors = []
        buses_tensors = []
        storage_tensors = []
        global_states = []

        for s in state:
            # 将 environment 转换成张量
            environment = s['environment']
            environment_tensor = torch.tensor([
                environment['temperature'],
                environment['horizontal_irradiation'],
                environment['pv_power'],
                environment['grid_price'],
                environment['ess_price']
            ], dtype=torch.float32)

            # 将 buses 转换成张量
            buses = s['buses']
            buses_tensor = torch.tensor([
                [bus['current_trip'] if bus['current_trip'] is not None else -1,  # 将 None 替换为 -1
                 1.0 if bus['is_departing_soon'] else 0.0,
                 bus['time_to_next_departure'] if bus['time_to_next_departure'] is not None else 100000,
                 bus['average_e'],
                 bus['soc'],
                 bus['continuous_charging_time']]
                for bus in buses
            ], dtype=torch.float32)

            # 将 storage 转换成张量
            storage = s['storage']
            storage_tensor = torch.tensor([
                storage['soc'],
                storage['continuous_charging_time']
            ], dtype=torch.float32)

            # 拼接三个部分的张量形成 global_state 张量
            global_state = torch.cat((
                environment_tensor,
                buses_tensor.flatten(),  # 将 buses_tensor 拉平成一维张量
                storage_tensor
            ))

            # 将结果添加到对应的列表中
            environment_tensors.append(environment_tensor)
            buses_tensors.append(buses_tensor)
            storage_tensors.append(storage_tensor)
            global_states.append(global_state)

        # 将列表转换为批次张量
        environment_tensor_batch = torch.stack(environment_tensors)
        buses_tensor_batch = torch.stack(buses_tensors)
        storage_tensor_batch = torch.stack(storage_tensors)
        global_state_batch = torch.stack(global_states)

        # 如果输入是单个state，返回单个张量
        if len(environment_tensor_batch) == 1:
            return environment_tensor_batch[0], buses_tensor_batch[0], storage_tensor_batch[0], global_state_batch[0]

        return environment_tensor_batch, buses_tensor_batch, storage_tensor_batch, global_state_batch


    def calculate_trip_energy(self, distance, travel_time, temperature):
            """计算班次能耗的函数"""
            ln_L_n = np.log(distance)
            ln_F_k = np.log(self.bus_mass)
            ln_T_n = np.log(travel_time)
            temp_diff = abs(temperature - self.optimal_temperature)
            ln_E_kn = -8.11 + 0.5523 * ln_L_n + 0.78 * ln_F_k + 0.35 * ln_T_n + 0.0077 * temp_diff

            return np.exp(ln_E_kn)

def generate_random_numbers():
    result1 = []
    for _ in range(24):
        number = random.randint(0, 3)
        result1.append(number)
    result2 = random.randint(0, 2)
    return result1, result2

# env = ElectricBusChargingEnv()
# for i in range(3):
#     state_ini, ini_prev_actions, current_date,is_extrame = env.reset(i)
#         # print("i", i, "ini_prev_actions, self.current_date", ini_prev_actions, current_date,'\n', "state", state)
#     print("i", i, "ini_prev_actions, self.current_date", ini_prev_actions, current_date)
#     print("state测试", '\n', state_ini['buses'][0], '\n', state_ini['buses'][8], '\n', state_ini['buses'][17])
#     if is_extrame:
#         print("处于极端天气")
    # for p in range(12):
    #     bus_action, storge_action = generate_random_numbers()
    #     # (state, reward1, reward2, reward_3, reward_1, reward_2, done, charging_fee, fina_bus_actions,
    #     #  fina_storage_action, violate_constraint) = env.step(state_ini, ini_prev_actions, bus_action, storge_action, i)
    #     # print("episode", i, "step", p, '\n', reward1, reward2, reward_3, reward_1, reward_2, done, charging_fee, fina_bus_actions,
    #     #  fina_storage_action, violate_constraint)
    #     # print("state测试1", '\n', state['buses'][0], '\n', state['buses'][8], '\n', state['buses'][17])
    #     # state_ini = state
    #     # ini_prev_actions  = (bus_action, storge_action)



        # print("timetables", env.timetables)
        # print("vehicle_schedules", env.vehicle_schedules)
    # print("schedules", env.schedules)
        # print("daily_data", env.daily_data)
        # print("trip_weather_info", env.trip_weather_info)
        # print("route_average_consumptiomn", env.route_average_consumptiomn)
        # print("trip_status", env.trip_status)



